package co.edu.uniandes.services;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import co.edu.uniandes.dto.Ciudad;
import co.edu.uniandes.services.constantes.ConsultaConstantes;

/**
 * 
 * @author Rafael Guillermo Blanco Banquez <rafaelg.blancob@gmail.com>
 * 
 */
public class ServicioCiudad extends UnicastRemoteObject implements
		IServicioCiudad {

	/**
	 * Contructor
	 * 
	 * @throws RemoteException
	 */
	public ServicioCiudad() throws RemoteException {
		super();
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Se encarga de insertar los datos de una ciudad en BD
	 * 
	 * @param Ciudad
	 *            Datos de la ciudad
	 * @throws Exception
	 *             En caso de que los datos no hayan sido diligenciados.
	 *             Adicionalmente se va a lanzar una excepcion en caso de que se
	 *             presenten problemas con la base de datos
	 */
	@Override
	public void insertar(Ciudad ciudad) throws Exception {
		PreparedStatement ps = null;

		try {
			if (ciudad == null || ciudad.getNombre() == null
					|| ciudad.getPais() == 0) {
				throw new Exception(
						"No se puede guardar la ciudad ya que tiene datos sin diligenciar");
			}
			Connection conexion = ConexionBD.getInstance().getConection();
			ps = conexion.prepareStatement(ConsultaConstantes.INSERT_CIUDAD);
			ps.setString(1, ciudad.getNombre());
			ps.setDouble(2, ciudad.getLatitud());
			ps.setDouble(3, ciudad.getLongitud());
			ps.setInt(4, ciudad.getPais());

			ps.execute();
		} catch (Exception e) {
			throw e;
		} finally {
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}

		}
	}

	/**
	 * Metodo que consulta un Objeto en la base de datos
	 * 
	 * @return
	 */
	public List<Ciudad> consultar() throws Exception {
		
		Connection conexion = ConexionBD.getInstance().getConection();
		PreparedStatement ps = null;
		ResultSet rs = null;
		List<Ciudad> resultado = new ArrayList<Ciudad>();
		try {
			ps = conexion.prepareStatement(ConsultaConstantes.CONSULTA_CIUDAD);
			rs = ps.executeQuery();
			Ciudad ciudad;
			while (rs.next()) {
				ciudad = new Ciudad();
				ciudad.setId(rs.getInt("id"));
				ciudad.setNombre(rs.getString("nombre"));
				ciudad.setLongitud(rs.getDouble("longitud"));
				ciudad.setLatitud(rs.getDouble("latitud"));
				ciudad.setPais(rs.getInt("idPais"));
				resultado.add(ciudad);
			}
		} catch (Exception e) {
			throw e;
		} finally {
			if (rs != null && !rs.isClosed()) {
				rs.close();
			}
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}
		}
		return resultado;
		
	}

	/**
	 * Obtiene las ciudades que se encuentran en persistencia de acuerdo con el
	 * pais en el que se encuentrna
	 * 
	 * @param pais
	 *            Identificador del pais
	 * @return Lista de ciudades que se encuentran en el pais ingresado por
	 *         parametro
	 * @throws Exception
	 *             Cuando hay problemas con la base de datos
	 */
	public List<Ciudad> consultarPais(Integer pais) throws Exception {
		
		Connection conexion = ConexionBD.getInstance().getConection();
		PreparedStatement ps = null;
		ResultSet rs = null;
		List<Ciudad> resultado = new ArrayList<Ciudad>();
		try {
			ps = conexion.prepareStatement(ConsultaConstantes.CONSULTA_CIUDAD_POR_PAIS);
			ps.setInt(1, pais);
			rs = ps.executeQuery();
			Ciudad ciudad;
			while (rs.next()) {
				ciudad = new Ciudad();
				ciudad.setId(rs.getInt("id"));
				ciudad.setNombre(rs.getString("nombre"));
				ciudad.setLongitud(rs.getDouble("longitud"));
				ciudad.setLatitud(rs.getDouble("latitud"));
				ciudad.setPais(rs.getInt("idPais"));
				resultado.add(ciudad);
			}
		} catch (Exception e) {
			throw e;
		} finally {
			if (rs != null && !rs.isClosed()) {
				rs.close();
			}
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}
		}
		return resultado;
	}

	/**
	 * Se encarga de eliminar una ciudad identificada con cierto id
	 * 
	 * @param id
	 *            Identificacion de la ciudad
	 * @throws Exception
	 *             Cuando la identificacion de la ciudad es nula o cuando se
	 *             presenta problemas con la BD
	 */
	@Override
	public void eliminar(Integer id) throws Exception {

		PreparedStatement ps = null;
		if (id == null) {
			throw new Exception(
					" La identificacion de la ciudad que se va a eliminar es nula");
		}
		try {
			Connection connection = ConexionBD.getInstance().getConection();
			ps = connection.prepareStatement(ConsultaConstantes.DELETE_CIUDAD);
			ps.setInt(1, id);
			ps.execute();
		} catch (Exception e) {
			throw e;
		} finally {
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}
		}
	}

	/**
	 * Se encarga de modificar los datos de una ciudad en BD
	 * 
	 * @param Ciudad
	 *            Datos de la ciudad
	 * @throws Exception
	 *             En caso de que los datos de la ciudad no hayan sido
	 *             diligenciados. Adicionalmente se va a lanzar una excepcion en
	 *             caso de que se presenten problemas con la base de datos
	 */
	@Override
	public void modificar(Ciudad ciudad) throws Exception {
		PreparedStatement ps = null;

		try {
			if (ciudad == null || ciudad.getNombre() == null
					|| ciudad.getPais() == 0) {
				throw new Exception(
						"No se puede guardar la ciudad ya que tiene datos sin diligenciar");
			}
			Connection conexion = ConexionBD.getInstance().getConection();
			ps = conexion.prepareStatement(ConsultaConstantes.UPDATE_CIUDAD);
			ps.setString(1, ciudad.getNombre());
			ps.setDouble(2, ciudad.getLatitud());
			ps.setDouble(3, ciudad.getLongitud());
			ps.setInt(4, ciudad.getPais());
			ps.setInt(5, ciudad.getId());

			ps.execute();
		} catch (Exception e) {
			throw e;
		} finally {
			if (ps != null && !ps.isClosed()) {
				ps.close();
			}

		}

	}

	/**
	 * Metodo que returna una lista de Ciudades Dispinibles
	 * 
	 * @return Vector[]
	 */
	public Vector<String> obtenerCiudades(Integer idPais) {
		Vector<String> vector = new Vector<String>();

		// Llenamos el Vector con las por pais

		return vector;

	}

}
